package com.ruoyi.utils;

import fr.opensagres.poi.xwpf.converter.core.ImageManager;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.ruoyi.utils.DocxGenerator.createDocx;

/**
 * @Classname FileToURL
 * @Description TODO
 * @Date 2025/3/24 15:04
 * @Created by xxx
 */

/**
 * poi WordToHtml工具类
 */
@Slf4j
public class WordToHtml {

    private static InputStream readInputStrem(InputStream inputStream) {
        String regEx_special = "width:595\\.3pt;";
        String regEx_special2 = "white-space:pre-wrap;";
        String replace = "white-space:pre-wrap;word-break:break-all;";

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }

            // 关键修改点1：指定UTF-8编码读取字节流
            String content = baos.toString(StandardCharsets.UTF_8.name());

            // 关键修改点2：添加meta charset声明
            content = content.replace("<head>", "<head><meta charset=\"UTF-8\">");

            Pattern compile = Pattern.compile(regEx_special, Pattern.CASE_INSENSITIVE);
            Matcher matcher = compile.matcher(content);
            String replaceAll = matcher.replaceAll("");

            Pattern compile2 = Pattern.compile(regEx_special2, Pattern.CASE_INSENSITIVE);
            Matcher matcher2 = compile2.matcher(replaceAll);
            String replaceAll2 = matcher2.replaceAll(replace);

            return new ByteArrayInputStream(replaceAll2.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            log.error("错误信息：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 清空文件内容
     *
     * @param fileName
     */
    public static void clearInfoForFile(String fileName) {
        File file = new File(fileName);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write("");
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // public static void main(String[] args) {
    // long timeMillis = System.currentTimeMillis();
    // log.info("开始转换！");
    // String wordFilePath =
    // "C:/develop/project/upload/files/1/text/8bf17cd2-f043-40cb-9552-c9e98bce2eb7.docx";
    // String htmlFilePath =
    // "C:/develop/project/upload/files/1/text/8bf17cd2-f043-40cb-9552-c9e98bce2eb7.html";
    // File file = WordToHtml.wordToHtml(wordFilePath, htmlFilePath);
    // // 读取html文件
    // if (file != null) {
    // log.info("文件存放路径：{}",file.getPath());
    // log.info("转换结束！用时：{}ms",System.currentTimeMillis()-timeMillis);
    // return;
    // }
    // log.error("文件转换失败！");
    // }
    public static String wordToHtml(String wordPath, boolean isFirstParagraph) throws Exception {
        FileInputStream fis = new FileInputStream(wordPath);
        XWPFDocument document = new XWPFDocument(fis);
        String html = convertToHTML(document, isFirstParagraph);
        return html;
    }

    private static String convertToHTML(XWPFDocument document, boolean isFirstParagraph) {
        StringBuilder htmlBuilder = new StringBuilder();
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            String text = paragraph.getText();
            if (text == null || text.isEmpty()) continue;

            if (isFirstParagraph) {
                // 第一行：强制使用居中的 <h1>
                htmlBuilder.append("<h1 style=\"text-align: center;\">")
                        .append(text)
                        .append("</h1>");
                isFirstParagraph = false;
            } else {
                // 其他段落：根据对齐方式生成标签
                boolean isCenterAligned = paragraph.getAlignment() == ParagraphAlignment.CENTER;
                String tag = isCenterAligned ? "h1" : "p";
                String style = isCenterAligned ? " style=\"text-align: center;\"" : "";

                htmlBuilder.append("<").append(tag).append(style).append(">")
                        .append(text)
                        .append("</").append(tag).append(">");
            }
        }
        return htmlBuilder.toString();
    }

    private static void saveHTMLToFile(String html) throws IOException {
        File file = new File("path/to/output.html");
        BufferedWriter writer = new BufferedWriter(new FileWriter(file));
        writer.write(html);
        writer.close();
    }

    public static void base64ToFile(String base64, String filePath) throws IOException {
        byte[] buffer = Base64.getDecoder().decode(base64);
        File file = new File(filePath);
        File parentDir = file.getParentFile();
        Files.createDirectories(parentDir.toPath());
        // 确保目录存在
        if (!parentDir.exists() && !parentDir.mkdirs()) {
            throw new IOException("无法创建目录: " + parentDir);
        }
        try (FileOutputStream out = new FileOutputStream(file)) {
            out.write(buffer);
        }
    }


    /**
     * html 流文件 修改内容 width:595.3pt; 因为转换的HTML页面默认内容区域不是html自适应大小，内容位置不对
     *
     * @param parentDirectory html文件所在文件夹
     * @param filename        html旧文件地址
     * @param newName         html新文件地址
     * @return
     */
    private File htmlreplace(String parentDirectory, String filename, String newName) {
        try (FileInputStream inputStream = new FileInputStream(new File(parentDirectory + filename + ".html"))) {
            InputStream inputStrem = readInputStrem(inputStream);
            clearInfoForFile(parentDirectory + filename + ".html");

            byte[] buffer = new byte[inputStrem.available()];
            inputStrem.read(buffer);

            try (OutputStream outStream = new FileOutputStream(new File(parentDirectory + newName + ".html"))) {
                outStream.write(buffer);
            }
            return new File(parentDirectory + newName + ".html");
        } catch (IOException e) {
            log.error("Html转换失败！", e);
            return null;
        }
    }

    private File docxConvert(String parentDirectory, String filename, String newName) {
        try (FileInputStream fis = new FileInputStream(filename);
             OutputStream out = new FileOutputStream(new File(parentDirectory + newName + ".html"))) {

            XWPFDocument document = new XWPFDocument(fis);
            XHTMLOptions options = XHTMLOptions.create()
                    .setImageManager(new ImageManager(new File(parentDirectory), UUID.randomUUID().toString()))
                    .indent(4);

            XHTMLConverter.getInstance().convert(document,
                    out,
                    options);
        } catch (IOException ex) {
            log.error("word转化出错！", ex);
            return null;
        }
        return htmlreplace(parentDirectory, newName, newName);

    }
    public static void convertHTMLToWord(String htmlContent, String outputPath) throws Exception {
        XWPFDocument document = new XWPFDocument();

        // 使用Jsoup解析HTML
        Document htmlDoc = (Document) Jsoup.parse(htmlContent);

        // 处理所有h1和p标签
        processHeadings(htmlDoc.select("h1"), document, ParagraphAlignment.CENTER);
        processParagraphs(htmlDoc.select("p"), document, ParagraphAlignment.LEFT);

        // 保存文档
        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            document.write(out);
        }
    }

    private static void processHeadings(Elements headings, XWPFDocument document, ParagraphAlignment alignment) {
        for (Element element : headings) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.setAlignment(alignment);
            processContent(element, paragraph);
        }
    }

    private static void processParagraphs(Elements paragraphs, XWPFDocument document, ParagraphAlignment alignment) {
        for (Element element : paragraphs) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.setAlignment(alignment);
            processContent(element, paragraph);
        }
    }

    private static void processContent(Element element, XWPFParagraph paragraph) {
        for (Node node : element.childNodes()) {
            processNode(node, paragraph.createRun());
        }
    }

    private static void processNode(Node node, XWPFRun run) {
        if (node instanceof TextNode) {
            // 处理文本节点
            run.setText(((TextNode) node).text());
        } else if (node instanceof Element) {
            Element elem = (Element) node;

            // 创建新Run保留父样式
            XWPFRun styledRun = run.getParagraph().createRun();
            inheritStyle(run, styledRun);

            // 设置样式
            applyStyle(elem, styledRun);

            // 递归处理子节点
            for (Node child : elem.childNodes()) {
                processNode(child, styledRun);
            }
        }
    }

    private static void inheritStyle(XWPFRun source, XWPFRun target) {
        // 继承基础样式
        target.setColor(source.getColor());
        target.setFontSize(source.getFontSize());
        target.setBold(source.isBold());
        target.setItalic(source.isItalic());
        target.setUnderline(source.getUnderline());
    }

    private static void applyStyle(Element element, XWPFRun run) {
        String tagName = element.tagName().toLowerCase();

        // 基础文本样式
        switch (tagName) {
            case "b":
            case "strong":
                run.setBold(true);
                break;
            case "i":
            case "em":
                run.setItalic(true);
                break;
            case "u":
                run.setUnderline(UnderlinePatterns.SINGLE);
                break;
        }

        // 处理内联样式（简易版）
        String style = element.attr("style");
        if (!style.isEmpty()) {
            for (String prop : style.split(";")) {
                String[] kv = prop.split(":");
                if (kv.length == 2) {
                    String key = kv[0].trim();
                    String value = kv[1].trim();
                    switch (key) {
                        case "color":
                            run.setColor(value.replace("#", ""));
                            break;
                        case "font-size":
                            try {
                                run.setFontSize(Integer.parseInt(value.replace("px", "")));
                            } catch (NumberFormatException ignored) {}
                            break;
                    }
                }
            }
        }
    }
}
